package config

import (
	"github.com/ihaiker/tfwrapper/internal/util"
	"github.com/zclconf/go-cty/cty"
	"path"
	"path/filepath"
)

const WrapperConfigFile = "tfwrapper.hcl"

type Running struct {
	WrapperConfigPath string //tfwrapper.hcl 目录
	CurrentConfigPath string //当前配置文件路径

	TerraformVersionConstraint *string `hcl:"terraform_version_constraint" cty:"terraform_version_constraint"` //指定terraform版本
	TFWrapperVersionConstraint *string `hcl:"tfwrapper_version_constraint" cty:"tfwrapper_version_constraint"` //指定tfwrapper版本
	TerraformBinary            *string `hcl:"terraform_binary" cty:"terraform_binary"`                         //指定terraform运行文件

	DownloadDir    *string `hcl:"download_dir" cty:"download_dir"`       //下载目录
	AutoInputs     *bool   `hcl:"auto_inputs" cty:"auto_inputs"`         //自动输入
	NonInteractive *bool   `hcl:"non_interactive" cty:"non_interactive"` //非交互模式
	Parallelism    *uint   `hcl:"parallelism" cty:"parallelism"`         //并行数

	TerraformVersion string //当前terraform版本
	TFWrapperVersion string //当前版本

	WorkingDir string //工作目录

	ModuleName string //当前模块名称
	ModuleDir  string //当前模块的真实路径

	Stack           string   //stack
	StackSourceDir  string   //当前执行的stack source 目录
	StackSourcesDir []string //所有的 stack source 目录

	Globals map[string]cty.Value
	Locals  map[string]cty.Value

	Inputs map[string]cty.Value

	Terraform  *Terraform
	Generators Generators

	Environments map[string]string

	Functions []Function
}

func (r Running) GetTerraformBinary() string {
	if r.TerraformBinary != nil {
		return *r.TerraformBinary
	}
	return "terraform"
}

func (r Running) RelPath() string {
	if r.CurrentConfigPath == "" {
		return ""
	} else {
		p, _ := filepath.Rel(path.Dir(r.WrapperConfigPath), r.CurrentConfigPath)
		if p == "." {
			return filepath.Base(r.CurrentConfigPath)
		}
		return p
	}
}

func (r Running) RelDirPath() string {
	p, _ := filepath.Rel(path.Dir(r.WrapperConfigPath), r.WorkingDir)
	if p == "." {
		return filepath.Base(r.WorkingDir)
	}
	return p
}

func Clone(withes ...Running) Running {
	r := Running{}
	for _, rc := range withes {
		r.WrapperConfigPath = util.Switch(rc.WrapperConfigPath, r.WrapperConfigPath)

		r.TerraformBinary = util.SwitchString(rc.TerraformBinary, r.TerraformBinary)
		r.TFWrapperVersionConstraint = util.SwitchString(rc.TFWrapperVersionConstraint, r.TFWrapperVersionConstraint)
		r.TerraformVersionConstraint = util.SwitchString(rc.TerraformVersionConstraint, r.TerraformVersionConstraint)
		r.DownloadDir = util.SwitchString(rc.DownloadDir, r.DownloadDir)
		r.AutoInputs = util.SwitchBool(rc.AutoInputs, r.AutoInputs)
		r.NonInteractive = util.SwitchBool(rc.NonInteractive, r.NonInteractive)
		r.Parallelism = util.SwitchUint(rc.Parallelism, r.Parallelism)

		r.TerraformVersion = util.Switch(rc.TerraformVersion, r.TerraformVersion)
		r.TFWrapperVersion = util.Switch(rc.TFWrapperVersion, r.TFWrapperVersion)

		r.WorkingDir = util.Switch(rc.WorkingDir, r.WorkingDir)
		r.ModuleName = util.Switch(rc.ModuleName, r.ModuleName)
		r.ModuleDir = util.Switch(rc.ModuleDir, r.ModuleDir)
		r.Stack = util.Switch(rc.Stack, r.Stack)
		r.StackSourceDir = util.Switch(rc.StackSourceDir, r.StackSourceDir)
		r.StackSourcesDir = rc.StackSourcesDir

		r.Globals = util.Merge(r.Globals, rc.Globals)
		r.Locals = util.Merge(r.Locals, rc.Locals)
		r.Inputs = util.Merge(r.Inputs, rc.Inputs)

		r.Generators = MergeGenerators(r.Generators, rc.Generators)
		r.Terraform = MergeTerraform(r.Terraform, rc.Terraform)

		r.Functions = MergeFunction(r.Functions, rc.Functions)
		r.Environments = util.MergeMapString(r.Environments, rc.Environments)
	}
	return r
}

type TFWrapperConfig struct {
	Stacks     *Stacks
	Encryption *Encryption

	StackFileConfig
}

type StackFileConfig struct {
	Running

	Modules []*Module
}

type StackConfig struct {
	Stack Stack

	Running

	Files []*StackFileConfig
}
